package br.unidocs.web.bean;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Calendar;
import java.util.List;

import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.component.html.HtmlDataTable;
import javax.faces.context.FacesContext;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

import org.apache.myfaces.custom.fileupload.UploadedFile;

import br.unidocs.modelo.entidade.Arquivo;
import br.unidocs.modelo.entidade.Comentario;
import br.unidocs.modelo.entidade.Usuario;
import br.unidocs.servico.ArquivoEJB;

public class ArquivoBackingBean {
	// Campos utilizados para o upload de arquivos
	private String tags;
	private String descricao;
	private UploadedFile uploadedFile;

	// Campos utilizados para a pesquisa de arquivos
	private String tagsPesquisa;
	private List<Arquivo> arquivosPesquisados;

	private HtmlDataTable tabelaResultados;

	// Campos utilizados para o detalhamento de arquivo
	private Arquivo arquivo;
	private String novoComentario;

	@EJB
	private ArquivoEJB arquivoEJB;

	public void fazDownload() {
		// Localiza o arquivo no diretorio padrão a partir do ID

		File f = new File("c:\\Temp\\" + arquivo.getId() + ".bin");
		BufferedInputStream bis = null;
		try {
			// fis = new FileInputStream(f);
			// if (f.length() > Integer.MAX_VALUE) {
			// throw new RuntimeException(
			// "Arquivo muito grande para ser armazenado em um byte[]!");
			// }
			// byte[] bin = new byte[(int) f.length()];
			// int offset = 0;
			// int numRead = 0;
			// while (offset < bin.length
			// && (numRead = fis.read(bin, offset, bin.length - offset)) >= 0) {
			// offset += numRead;
			// }
			//
			// if (offset < bin.length) {
			// throw new RuntimeException(
			// "Não conseguiu ler completamente o arquivo "
			// + f.getName());
			// }
			HttpServletResponse response = (HttpServletResponse) FacesContext
					.getCurrentInstance().getExternalContext().getResponse();
			response.setContentType("application/force-download");
			response.addHeader("Content-Disposition", "attachment; filename=\""
					+ arquivo.getNome() + "\"");
			response.setContentLength((int) f.length());

			bis = new BufferedInputStream(new FileInputStream(f));
			ServletOutputStream sos = response.getOutputStream();
			byte[] bin = new byte[1024];
			int length = 0;
			while ((bis != null) && ((length = bis.read(bin)) != -1)) {
				sos.write(bin, 0, length);
			}
			sos.close();
			FacesContext.getCurrentInstance().responseComplete();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			throw new RuntimeException("Arquivo não localizado: " + f.getName());
		} catch (IOException e) {
			e.printStackTrace();
			throw new RuntimeException("Erro ao ler o arquivo: " + f.getName());
		} finally {
			if (bis != null) {
				try {
					bis.close();
				} catch (IOException e) {
					e.printStackTrace();
					throw new RuntimeException("Erro ao fechar o arquivo.", e);
				}
			}
		}
	}

	public String adicionaComentario() {
		Comentario comentario = new Comentario();
		comentario.setDataCriacao(Calendar.getInstance().getTime());
		comentario.setTexto(novoComentario);

		FacesContext facesCtx = FacesContext.getCurrentInstance();
		Usuario usuario = facesCtx.getApplication().evaluateExpressionGet(
				facesCtx, "#{loginBean.usuarioLogado}", Usuario.class);
		if (usuario != null) {
			comentario.setUsuario(usuario);
		}
		comentario.setArquivo(arquivo);
		arquivo.getComentarios().add(comentario);
		arquivo = arquivoEJB.atualizaArquivo(arquivo, null, null);
		novoComentario = "";

		return "postback";
	}

	public String selecionaArqTabela() {
		Arquivo tmp = (Arquivo) tabelaResultados.getRowData();
		arquivo = arquivoEJB.localizaArquivoParaDetalhamento(tmp.getId());
		return "detalheArquivo";
	}

	public String pesquisaArquivo() {
		String[] params = tagsPesquisa.split("\\s");
		arquivosPesquisados = arquivoEJB.pesquisaPorTags(params);
		if (arquivosPesquisados.size() == 1) {
			Arquivo tmp = arquivosPesquisados.get(0);
			arquivo = arquivoEJB.localizaArquivoParaDetalhamento(tmp.getId());
			return "detalheArquivo"; // quando tem apenas 1 resultado
		} else {
			return "selecionaArquivo";
		}
	}

	public String fazUpload() {
		// obter usuario logado no sistema
		FacesContext facesCtx = FacesContext.getCurrentInstance();
		Usuario usuario = facesCtx.getApplication().evaluateExpressionGet(
				facesCtx, "#{loginBean.usuarioLogado}", Usuario.class);

		// Processa as tags
		String[] arrayTags = tags.split("[;,]");
		Integer idArquivoCriado = null;
		try {
			idArquivoCriado = arquivoEJB.criaArquivo(uploadedFile.getName(),
					descricao, arrayTags, usuario, uploadedFile.getBytes());
		} catch (Exception e) {
			e.printStackTrace();
			FacesMessage msg = new FacesMessage(
					"Erro no upload do arquivo :( tente novamente mais tarde.");
			facesCtx.addMessage(null, msg);
		}
		// System.out.println("As tags para upload são: " + tags);
		// System.out.println("A descrição do arquivo é: " + descricao);
		// System.out.println("Os dados do arquivo são: ");
		// System.out.println("  Nome: " + arquivo.getName());
		// System.out.println("  Tamanho: " + arquivo.getSize());

		arquivo = arquivoEJB.localizaArquivo(idArquivoCriado);

		return "sucesso";
	}

	// private String filename;
	public String getTags() {
		return tags;
	}

	public void setTags(String tags) {
		this.tags = tags;
	}

	public String getDescricao() {
		return descricao;
	}

	public void setDescricao(String descricao) {
		this.descricao = descricao;
	}

	public UploadedFile getUploadedFile() {
		return uploadedFile;
	}

	public void setUploadedFile(UploadedFile uploadedFile) {
		this.uploadedFile = uploadedFile;
	}

	public Arquivo getArquivo() {
		return arquivo;
	}

	public void setArquivo(Arquivo arquivo) {
		this.arquivo = arquivo;
	}

	public String getTagsPesquisa() {
		return tagsPesquisa;
	}

	public void setTagsPesquisa(String tagsPesquisa) {
		this.tagsPesquisa = tagsPesquisa;
	}

	public List<Arquivo> getArquivosPesquisados() {
		return arquivosPesquisados;
	}

	public void setArquivosPesquisados(List<Arquivo> arquivosPesquisados) {
		this.arquivosPesquisados = arquivosPesquisados;
	}

	public HtmlDataTable getTabelaResultados() {
		return tabelaResultados;
	}

	public void setTabelaResultados(HtmlDataTable tabelaResultados) {
		this.tabelaResultados = tabelaResultados;
	}

	public String getNovoComentario() {
		return novoComentario;
	}

	public void setNovoComentario(String novoComentario) {
		this.novoComentario = novoComentario;
	}

}
